#include "spl.h"
#include "ota_common.h"
#include <stdio.h>
#include "crc.h"

static SPLPortable_t spl_portable;
static FIB_t *fib;

static const char *spl_banner = "\r\n\
┌──────────────┐\r\n\
│ Camellia SPL │\r\n\
└──────────────┘\r\n\
";

static const uint8_t FIB_MAGIC_NUMBER[4] = {'F','I','B',0};

static void SPL_printBanner(void){
    char str_buffer[64];
    spl_portable.print(spl_banner);
    /* 打印版本. */
    snprintf(str_buffer,sizeof(str_buffer) - 1,"Version:%d.%d.%d\r\n",CAMELLIA_SPL_VERSION_MAJOR,CAMELLIA_SPL_VERSION_MINOR,CAMELLIA_SPL_VERSION_REV);
    spl_portable.print(str_buffer);
    /* 打印作者. */
    spl_portable.print("Author: Leo I. J.\r\n");
    /* 打印编译日期. */
    snprintf(str_buffer,sizeof(str_buffer) - 1,"Build:%s %s\r\n",__DATE__,__TIME__);
    spl_portable.print(str_buffer);
}

static RET_t SPL_checkUpgradeFirmware(FIB_t *fib){
    uint16_t crc_cal = 0x0000;
    crc_cal = crc16(UPG_REGION_START_ADDR,fib->firmware_size);
    if ( crc_cal != fib->firmware_crc16 ){
        return RET_CRC16_CHECK_FAILED;
    }else{
        return RET_OK;
    }
    return RET_OK;
}

void SPL_run(SPLPortable_t portable){
    spl_portable = portable;
    /* 检查Portable相关接口. */
    if ( spl_portable.print == NULL ){
        return;
    }
    if ( spl_portable.flash_unlock == NULL ){
        spl_portable.print("[E][SPL] No flash unlock callback.\r\n");
        return;
    }
    if ( spl_portable.flash_lock == NULL ){
        spl_portable.print("[E][SPL] No flash lock callback.\r\n");
        return;
    }
    if ( spl_portable.flash_erase == NULL ){
        spl_portable.print("[E][SPL] No flash erase callback.\r\n");
        return;
    }
    if ( spl_portable.flash_copy == NULL ){
        spl_portable.print("[E][SPL] No flash copy callback.\r\n");
        return;
    }
    if ( spl_portable.firmware_load == NULL ){
        spl_portable.print("[E][SPL] No firmware load callback.\r\n");
        return;
    }
    /* Print banner. */
    SPL_printBanner();
    if ( FIB_REGION_SIZE <= 0 ){
        spl_portable.print("[E][SPL] No FIB region.\r\n");
        return;
    }
    fib = (FIB_t*)FIB_REGION_START_ADDR;
    /* 检查FIB有效性. */
    for ( int n = 0; n < 4; n++ ){
        if ( fib->magic_number[n] != FIB_MAGIC_NUMBER[n] ){
            spl_portable.print("[E][SPL] FIB magic number check error.\r\n");
            return;
        }
    }
    /* 检查更新标志. */
    if ( fib->upgrade_flag == UPG_FLAG_UPG ){
        /* 需要更新. */
        if ( SPL_checkUpgradeFirmware(fib) != RET_OK ){
            spl_portable.print("[E][SPL] CRC16 check failed.\r\n");
            return;
        }
        /* 擦除旧固件. */
        
    }
}